import OSS from 'ali-oss'
import { getOssTokenApi } from '@/api/oss'
import { ElMessage } from 'element-plus'

// CDN域名常量
const CDN_HOST = 'https://cdn.keketrtr.top'

interface OssConfig {
  accessKeyId: string
  accessKeySecret: string
  securityToken: string
  region: string
  bucket: string
  endpoint: string
}

interface UploadResult {
  url: string
  name: string
}

class OssUploader {
  private client: OSS | null = null
  private config: OssConfig | null = null
  private tokenExpiration: Date | null = null

  /**
   * 获取或刷新OSS配置
   */
  private async getOssConfig(): Promise<OssConfig> {
    // 如果配置存在且未过期，直接返回
    if (this.config && this.tokenExpiration && new Date() < this.tokenExpiration) {
      return this.config
    }

    try {
      const { data } = await getOssTokenApi()
      this.config = {
        accessKeyId: data.accessKeyId,
        accessKeySecret: data.accessKeySecret,
        securityToken: data.securityToken,
        region: data.region,
        bucket: data.bucket,
        endpoint: data.endpoint
      }
      
      // 设置过期时间（提前5分钟刷新）
      this.tokenExpiration = new Date(new Date(data.expiration).getTime() - 5 * 60 * 1000)
      
      return this.config
    } catch (error) {
      console.error('获取OSS配置失败:', error)
      throw new Error('获取OSS配置失败')
    }
  }

  /**
   * 获取或创建OSS客户端
   */
  private async getOssClient(): Promise<OSS> {
    const config = await this.getOssConfig()
    
    // 如果客户端不存在或配置已更新，重新创建
    if (!this.client || this.config !== config) {
      this.client = new OSS({
        accessKeyId: config.accessKeyId,
        accessKeySecret: config.accessKeySecret,
        stsToken: config.securityToken,
        region: config.region,
        bucket: config.bucket,
        endpoint: config.endpoint
      })
    }
    
    return this.client
  }

  /**
   * 生成文件名
   */
  private generateFileName(file: File, folder: string = 'images'): string {
    const timestamp = Date.now()
    const randomStr = Math.random().toString(36).substring(2, 8)
    const extension = file.name.split('.').pop()
    return `${folder}/${timestamp}_${randomStr}.${extension}`
  }

  /**
   * 验证文件
   */
  private validateFile(file: File): boolean {
    // 检查文件类型
    const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']
    if (!allowedTypes.includes(file.type)) {
      ElMessage.error('只支持上传 JPG、PNG、GIF、WebP 格式的图片')
      return false
    }

    // 检查文件大小（5MB）
    const maxSize = 5 * 1024 * 1024
    if (file.size > maxSize) {
      ElMessage.error('图片大小不能超过 5MB')
      return false
    }

    return true
  }

  /**
   * 上传文件到OSS
   */
  async uploadFile(file: File, folder: string = 'images'): Promise<UploadResult> {
    if (!this.validateFile(file)) {
      throw new Error('文件验证失败')
    }

    try {
      const client = await this.getOssClient()
      const fileName = this.generateFileName(file, folder)
      
      const result = await client.put(fileName, file)
      
      return {
        url: `${CDN_HOST}/${fileName}`,
        name: fileName
      }
    } catch (error) {
      console.error('文件上传失败:', error)
      ElMessage.error('文件上传失败，请重试')
      throw error
    }
  }

  /**
   * 批量上传文件
   */
  async uploadFiles(files: File[], folder: string = 'images'): Promise<UploadResult[]> {
    const uploadPromises = files.map(file => this.uploadFile(file, folder))
    return Promise.all(uploadPromises)
  }

  /**
   * 删除文件
   */
  async deleteFile(fileName: string): Promise<void> {
    try {
      const client = await this.getOssClient()
      await client.delete(fileName)
    } catch (error) {
      console.error('文件删除失败:', error)
      throw error
    }
  }
}

// 创建单例实例
const ossUploader = new OssUploader()

export default ossUploader
export type { UploadResult }